package com.smart.platform.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.smart.platform.common.ocr.OcrAccuracyLocationText;
import com.smart.platform.common.ocr.OcrOnlyText;
import com.smart.platform.common.ocr.Ocrpoint;
import com.smart.platform.common.ocr.PaddleOcrPostParam;
import com.smart.platform.service.Ocrservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Slf4j
@Service
public class Ocrserviceimpl implements Ocrservice {
    //保存的图片名称格式
    private final String FORMAT_IMG_NAME = "%s.%s";

    private static final String FORMAT_OCR_POINT_NAME = "point%s";

//    //图片保存路径
//    @Value("#{'${ocr.img-path}'}")
//    private String imgPath;

    @Value("#{'${ocr.paddle-ocr-url}'.split(',')}")
    private List<String> paddleUrlList;


    //通过AtomicLong对象实现加一计数保证线程安全问题
    private static AtomicLong paddleCount = new AtomicLong();

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public List<OcrOnlyText> ocrText(String imgPath) {
//        //1.将Base64编码保存为图片文件
//        String imgFullPath = saveImage(imgBase64,imgType);
        //2.调用flask接口实现ocr识别,并处理结果
        List<OcrAccuracyLocationText> ocrResultList = ocrImage(imgPath);

        return ocrResultList.stream()
                .map(ocrAccuracyLocationText -> new OcrOnlyText(ocrAccuracyLocationText.getText()))
                .collect(Collectors.toList());

    }

//    private String saveImage(String imgBase64,String imgType){
//        //通过雪花算法获取唯一自增Id
//        long imgId = YitIdHelper.nextId();
//        String imgName = String.format(FORMAT_IMG_NAME,imgId,imgType);
//        //图片完整的保存路径
//        String imgFullPath = String.format(imgPath,imgName);
//        //保存图片到服务器
//        Base64utils.base64ToImg(imgBase64,imgFullPath);
//        return imgFullPath;
//    }

    private List<OcrAccuracyLocationText> ocrImage(String imgPath){
        //1.对flask接口的调用
        //由于paddle-ocr在普通部署方式下，无法利用cpu多核，因此其中一种解决方法是部署多个paddle-ocr实例
        //paddleCount加一后，对paddleUrlList长度取余，以轮询每个paddleOcr的实例。实现简单的负载均衡，调用多个实例
        int index = (int)(paddleCount.incrementAndGet()%paddleUrlList.size());
        String ocrResult = restTemplate.postForObject(paddleUrlList.get(index),new PaddleOcrPostParam(imgPath),String.class);
        //2.对ocr结果处理
        JSONObject ocrResultJsonObject = JSONObject.parseObject(ocrResult);
        Integer code = ocrResultJsonObject.getInteger("code");

        //如果ocr接口调用失败，则返回异常信息
        if(code != 0){
            String errorMsg = ocrResultJsonObject.getString("msg");
            log.info(errorMsg);
        }
        //解析data字段对应的数据
        JSONArray dataJsonArray = ocrResultJsonObject.getJSONArray("data");
        JSONArray jsonArray1 = dataJsonArray.getJSONArray(0);

        List<OcrAccuracyLocationText> ocrAccuracyLocationTexts = new ArrayList<>(jsonArray1.size());

        for(int i = 0;i < jsonArray1.size();i++){
            JSONArray jsonArray2 = jsonArray1.getJSONArray(i);
            //获取坐标数组
            JSONArray jsonArrayLocation = jsonArray2.getJSONArray(0);
            Map<String,Ocrpoint> ocrpointMap = decodelocation(jsonArrayLocation);
            //获取字符与可信度数组
            JSONArray jsonArrayText = jsonArray2.getJSONArray(1);
            OcrAccuracyLocationText ocrAccuracyLocationText = decodetext(jsonArrayText,ocrpointMap);
            ocrAccuracyLocationTexts.add(ocrAccuracyLocationText);
        }
        return ocrAccuracyLocationTexts;
    }

    /**
     * 解析识别的文本的坐标
     * @param jsonArrayLocation
     * @return
     */
    private Map<String, Ocrpoint> decodelocation(JSONArray jsonArrayLocation){
        Map<String,Ocrpoint> locationMap = new HashMap<>(jsonArrayLocation.size());
        //从左上角开始顺时针四个角
        for(int i = 0;i < 4;i++){
            JSONArray locationArray = jsonArrayLocation.getJSONArray(i);
            String x = locationArray.getString(0);
            String y = locationArray.getString(1);
            Ocrpoint ocrpoint = new Ocrpoint(x,y);
            locationMap.put(String.format(FORMAT_OCR_POINT_NAME,i),ocrpoint);
        }
        return locationMap;
    }

    /**
     * 解析识别文本的内容和可信度
     * @param jsonArrayText
     * @param ocrpointMap
     * @return
     */
    private OcrAccuracyLocationText decodetext(JSONArray jsonArrayText, Map<String,Ocrpoint> ocrpointMap){
        String text = jsonArrayText.getString(0);
        String accuracy = jsonArrayText.getString(1);
        return new OcrAccuracyLocationText(text,accuracy,ocrpointMap);
    }


}
